FirelensでCloudWatch Logsにログ出力する際、特定JSONキーだけを出力する
こんにちは、岩城です。
小ネタです。
Firelens(Fluent Bit)を使ってCloudWatch Logにログ出力すると、アクセスログやアプリケーションのログだけ構わないのに、コンテナIDやECSタスクの情報などの情報も一緒にJSON形式出力されて見辛いと感じるケースがあります。
そんな時は、Fluent Bitの設定で特定のJSONキーの値のみを出力させるようにしましょう。
どういうことか
Fluent Bitの設定を以下のようにしたとします。
[OUTPUT] Name cloudwatch_logs Match * region ap-northeast-1 log_group_name /ecs/logs/hello-world-from-ecs-service log_stream_prefix from-fluentbit- auto_create_group true
東京リージョンのCloudWatch Logsにある/ecs/logs/hello-world-from-ecs-cluster
というロググループにfrom-fluentbit-
から始まるログストリームでログ出力します。
設定ファイルの設定について、もう少し詳しく知りたい方は以下エントリをご確認ください。とても分かりやすくまとまっています。
本題にもどります。
Firelensにより出力されるログ形式はデフォルトでJSON形式であり、本エントリ冒頭にあるとおり、コンテナやECSに関する情報が含まれます。
{ "container_id": "03c8dd594afa490bab06c3d791fec382-2254804424", "container_name": "hello-world-from-ecs-nginx", "source": "stdout", "log": "xxx.xxx.xxx.xxx - - [29/Nov/2021:07:20:58 +0000] \"GET / HTTP/1.1\" 200 64 \"-\" \"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.55 Safari/537.36\" \"-\"", "ecs_cluster": "hello-world-from-ecs-cluster", "ecs_task_arn": "arn:aws:ecs:ap-northeast-1:xxxxxxxxxxxx:task/hello-world-from-ecs-cluster/03c8dd594afa490bab06c3d791fec382", "ecs_task_definition": "hello-world-from-ecs-task-definition:24" }
これに関してはログだけを見た時、どのECSサービス、ECSタスク、コンテナから出力されたログか分からないので、情報として含まれることには意味があります。
ただし、CloudWatch Logsに出力させる場合、ロググループ名にECSサービス名を含めたり、ログストリーム名にECSタスクIDやコンテナ名が含めたりできるので、実際のログには不要だとするケースがあったりします。
そんな時、Fluent Bitの設定で特定JSONキーを指定して、アクセスログやアプリケーションログだけをCloudWatch Logsに出力させることができます。
特定JSONキーの値だけを出力させる
特定JSONキーの値だけを出力させるには、Fluent Bitの設定ファイルに1行付け足すだけです。
今回はlogキーだけを出力させたいのでlog_key log
とします。
[OUTPUT] Name cloudwatch_logs Match * region ap-northeast-1 log_group_name /ecs/logs/hello-world-from-ecs-cluster log_stream_prefix from-fluentbit- log_key log auto_create_group true
この状態でログ出力すると、logキーの中身だけが出力されるようになります。
logキーの値のみを指定してS3にログ出力する時は注意が必要
Firelensでは、Kinesis Data Firehoseを介してS3にログ出力することも可能です。
こちらもlogキーのみを指定してS3にログ出力できますが注意が必要です。
[OUTPUT] Name kinesis_firehose Match * region ap-northeast-1 log_key log delivery_stream ecs-delivery-stream
CloudWatch Logsの場合はロググループ名やログストリーム名にECSサービス名やコンテナ名、タスクIDを含められましたが、S3の場合は以下のようなフォルダ構成でログ出力されます。
ログの中身はこんな感じ。
xxx.xxx.xxx.xxx - - [29/Nov/2021:07:40:54 +0000] \"GET /favicon.ico HTTP/1.1\" 404 555 \"http://54.178.60.86/\" \"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.55 Safari/537.36\" \"-\" xxx.xxx.xxx.xxx - - [29/Nov/2021:07:40:53 +0000] \"GET / HTTP/1.1\" 200 64 \"-\" \"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.55 Safari/537.36\" \"-\" xxx.xxx.xxx.xxx - - [29/Nov/2021:07:40:54 +0000] \"GET / HTTP/1.1\" 304 0 \"-\" \"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.55 Safari/537.36\" \"-\"
以上より、ログだけあっても、どのECSサービス、コンテナ、タスクから出力されたログか分からなくなるため注意が必要です。
個人的にFirelensでS3にログ出力させる場合は、特定のJSONキーを指定せずに各種情報を含めた方が良いと感じました。
おわりに
本エントリがどなたかのお役に立てれば幸いです。